﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using Microsoft.Research.Kinect.Nui;
using Microsoft.Kinect;

namespace KinectApplication
{

    public enum ParserType
    {
        Depth,
        Skeleton,
        DepthAndSkeleton,
        Blob,
        Hand,
        PlayerIndexAndSkeleton
    }

    public class Kinect
    {
        public static KinectSensor _runtime = KinectSensor.KinectSensors[0];
        bool _isInit;

        public Kinect(ParserType type)
        {
            if (_isInit)
                UninitializeRuntime();


            /*
            switch (type)
            {
                case ParserType.PlayerIndexAndSkeleton:
                    _runtime .Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking);
                    _runtime.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
                    _runtime.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(_runtime_SkeletonFrameReady);
                    _runtime.DepthFrameReady += RuntimeDepthFrameReady;
                    break;
                default:
                    _runtime.Initialize(RuntimeOptions.UseDepth | RuntimeOptions.UseSkeletalTracking);
                    _runtime.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.Depth);
                    _runtime.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(_runtime_SkeletonFrameReady);
                    _runtime.DepthFrameReady += RuntimeDepthFrameReady;
                    break;
            }
            */

            _runtime.SkeletonStream.Enable();
            _runtime.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(_runtime_SkeletonFrameReady);
            _runtime.DepthStream.Enable();
            _runtime.DepthFrameReady += RuntimeDepthFrameReady;
            //_runtime.ColorStream.Enable(); // ??
            _runtime.Start();

            ParseType = type;
         
            _isInit = true;
        }

        private ParserType _parseType;
        public ParserType ParseType
        {
            get { return _parseType; }
            set
            {
                if (_parseType != value)
                {
                    _parseType = value;

                    if (value == ParserType.Skeleton)
                    {
                        TransformSmoothParameters parameters = _runtime.SkeletonStream.SmoothParameters;
                        parameters.Smoothing = 0.75F; //0.75F
                        parameters.Correction = 0.0F; //0.0F
                        parameters.Prediction = 0.0F; //0.0F
                        parameters.JitterRadius = 0.3F; //0.05
                        parameters.MaxDeviationRadius = 0.04F; //0.04F

                        /*
                        _runtime.SkeletonEngine.TransformSmooth = true;
                        _runtime.SkeletonEngine.SmoothParameters = new TransformSmoothParameters
                        {
                            Smoothing = 0.75F, //0.75F
                            Correction = 0.0F, //0.0F
                            Prediction = 0.0F, //0.0F
                            JitterRadius = 0.3F, //0.05
                            MaxDeviationRadius = 0.04F //0.04F
                        };
                        */

                    }
                    /*
                    else
                    {
                        // If ParserType doesn't have specific smoothparameters set above, turn off smoothing
                        _runtime.SkeletonEngine.TransformSmooth = false;
                    }
                    */
                }
            }
        }

        void _runtime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            switch (_parseType)
            {
                case ParserType.Blob:
                    break;
                case ParserType.Depth:
                    break;
                case ParserType.DepthAndSkeleton:
                    break;
                case ParserType.Hand:
                    break;
                case ParserType.PlayerIndexAndSkeleton:
                   // SkeletonParser.ParseSkeleton(e.SkeletonFrame);
                    break;
                case ParserType.Skeleton:
                    //SkeletonParser.ParseSkeleton(e.SkeletonFrame);
                    SkeletonParser.ParseSkeleton(e.OpenSkeletonFrame());
                    break;
            }
        }

        void RuntimeDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            switch (_parseType)
            {
                case ParserType.Blob:
                    // SkeletonParser.ParseDepth(e.ImageFrame);
                    BlobParser.ParseDepth(e.OpenDepthImageFrame());
                    break;
                case ParserType.Depth:
                    break;
                case ParserType.DepthAndSkeleton:
                    break;
                case ParserType.Hand:
                    break;
                case ParserType.PlayerIndexAndSkeleton:
                   // SkeletonParser.ParseDepth(e.ImageFrame);
                    break;
                case ParserType.Skeleton:
                    // SkeletonParser.ParseDepth(e.ImageFrame);
                    SkeletonParser.ParseDepth(e.OpenDepthImageFrame());
                    break;
            }


#if DEBUG
            if (_parseType == ParserType.PlayerIndexAndSkeleton)
            {
                DepthImageFrame frame = e.OpenDepthImageFrame();
                int arrayLength = frame.PixelDataLength;
                short[] shortArray = new short[arrayLength];
                frame.CopyPixelDataTo(shortArray);

                //e.OpenDepthImageFrame(). . ImageFrame.Image.Bits
                Debugging.ShowDepthWithPlayer(TempConvertToByteArray(shortArray, arrayLength), 320, 240);
            }
            else
            {
               // Debugging.ShowDepth(e.ImageFrame.Image.Bits, 640, 480);
            }
#endif
        }

        public void UninitializeRuntime()
        {
            if (_runtime != null)
            {

                _runtime.DepthFrameReady -= RuntimeDepthFrameReady;
                _runtime.SkeletonFrameReady -= _runtime_SkeletonFrameReady;

                _runtime.Stop();
            }

            _isInit = false;
        }

        public static byte[] TempConvertToByteArray(short[] shortArray, int length)
        {
            byte[] byteArray = new byte[length];

            for (int i = 0; i < length; ++i)
            {
                byteArray[i] = (byte)shortArray[i];
            }

            return byteArray;
        }
    }
}


//if (neuralNetwork != null && neuralNetwork.done)
//{
//    neuralNetwork.Recognize(arr, ref MatchedHigh, ref OutputValueHight, ref MatchedLow, ref OutputValueLow);
//}

//if (MatchedHigh == "Hs" && OutputValueHight > 0.8)
//{
//    NativeMethods.SendMouseInput(x, y, (int)System.Windows.SystemParameters.PrimaryScreenWidth, (int)System.Windows.SystemParameters.PrimaryScreenHeight, false);
//}